package com.css.fxfzaqbz.base.upload.controller;

import com.css.fxfzaqbz.base.upload.entity.AttachmentInfoEntity;
import com.css.fxfzaqbz.base.upload.service.AttachmentInfoService;
import com.css.fxfzaqbz.base.response.RestResponse;
import com.css.fxfzaqbz.modules.assess1.entity.ReportHuiXianEntity;
import com.css.fxfzaqbz.modules.base.service.HypergraphService;
import com.css.fxfzaqbz.modules.data.repository.ReportTemplateRepository;
import com.css.fxfzaqbz.util.PlatformObjectUtils;
import com.css.fxfzaqbz.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author Dbj
 * @date 2022年08月01日  16:40
 * @desc 附件的上传和下载
 */
@RestController
@Slf4j
@RequestMapping("/attachment")
public class AttachmentController {

    @Value("${image.localDir}")
    private String localDir;

    @Autowired
    private AttachmentInfoService attachmentInfoService;

    @Autowired
    private HypergraphService hypergraphService;

    /**
     * 文件上传
     */
    @PostMapping("/uploadFile")
    public RestResponse uploadFile(List<MultipartFile> file){
        RestResponse restResponse = null;
        if (file.size()==0) {
            restResponse = RestResponse.fail("上传失败，请选择文件");
            return restResponse;
        }
        if(file.size()>50){
            restResponse = RestResponse.fail("上传失败，请将上传的文件控制在50个以内");
            return restResponse;
        }
        List<String> attachmentInfoIdList = new ArrayList<String>();
        List<AttachmentInfoEntity> attachmentInfoEntities = new ArrayList<>();
        for(int i = 0;i<file.size();i++){
            if(file.get(i) != null){
                MultipartFile multipartFile = file.get(i);
                try {
                    //获取文件名称
                    String fileName=multipartFile.getOriginalFilename();
                    //获取文件上传的本地路径
                    String dateDir = new SimpleDateFormat("/yyyy/MM/dd").format(new Date());
                    String savePath = localDir + dateDir;
                    //构建文件
                    assert fileName != null;
                    //上传文件
                    String realFileName = uploadFile(fileName,savePath,multipartFile);
                    //构建实体类
                    AttachmentInfoEntity attachmentInfoEntity = buildAttachment(fileName,dateDir,realFileName);
                    attachmentInfoIdList.add(attachmentInfoEntity.getAttachId());
                    attachmentInfoEntities.add(attachmentInfoEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                    restResponse = RestResponse.fail("文件上传失败");
                    return restResponse;
                }
            }
        }
        int flag = 0;
        //保存附件到数据库
        if(ObjectUtils.isNotEmpty(attachmentInfoEntities)){
            flag = attachmentInfoService.save(attachmentInfoEntities);
        }

        //上传成功返回文件名用于业务实体保存
        if(flag==1){
            restResponse = RestResponse.succeed(attachmentInfoEntities);
            restResponse.setMessage("上传成功!");
        } else {
            restResponse = RestResponse.fail("文件上传失败");
        }
        return restResponse;
    }
    private String uploadFile(String fileName, String savePath, MultipartFile multipartFile) throws IOException {
        // 获取文件的后缀名
        assert fileName != null;
        String preFileName = fileName.substring(0, fileName.lastIndexOf("."));
        // .jpg  .pdf  .txt  .docs
        String fileType = fileName.substring(fileName.lastIndexOf("."));
        // 拼文件名  真实的文件名称
        String realFileName = preFileName + "_" + System.currentTimeMillis() + fileType;
        //判断文件夹是否存在如果不存在则创建
        if (!new File(savePath).exists()) {
            new File(savePath).mkdirs();
        }
        File file = new File(savePath, realFileName);
        multipartFile.transferTo(file);
        return realFileName;
    }

    private AttachmentInfoEntity buildAttachment(String fileName, String dateDir, String realFileName) {
        AttachmentInfoEntity attachmentInfoEntity = new AttachmentInfoEntity();
        attachmentInfoEntity.setAttachId(StringUtils.buildPrimaryId());
        attachmentInfoEntity.setAttachName(fileName);
        attachmentInfoEntity.setAttachPath(dateDir + "/" + realFileName);
        attachmentInfoEntity.setFileDirId(localDir);
        attachmentInfoEntity.setIsValid("1");
        attachmentInfoEntity.setIsCompleted("1");
        return attachmentInfoEntity;
    }

    /**
     * 文件下载
     *
     * @param attachId 附件id
     */
    @GetMapping(value = "/downLoadFile")
    public void downloadFile(@RequestParam("attachId") String attachId) {
        OutputStream os = null;
        InputStream is = null;
        try {
            //根据id和文件名获取真实的放在磁盘上的文件
            AttachmentInfoEntity attachmentInfoEntity = attachmentInfoService.getAttach(attachId);
            String attachPath = attachmentInfoEntity.getAttachPath();
            if (org.apache.commons.lang3.StringUtils.isNotBlank(attachPath)) {
                // 防乱码
//                    String name =
//                        new String(realFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
                ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                assert requestAttributes != null;
                HttpServletResponse response = requestAttributes.getResponse();
                assert response != null;
                response.reset();
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(attachmentInfoEntity.getAttachName(), "UTF-8") + "\"");
                // 跨域
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setHeader("Access-Control-Allow-Method", "POST,GET");
                String name = localDir + attachPath;
                is = new FileInputStream(new File(name));

                // PrintWrite pw=response.getWriter();  或
                os = response.getOutputStream();
                int flag = 0;
                while ((flag = is.read()) != -1) {
                    os.write(flag);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (os != null) {
                    os.flush();
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 文件下载
     *
     * @param attachId 附件id
     */
    @GetMapping(value = "/downLoad")
    public void download(@RequestParam("attachId") String attachId) {
        OutputStream os = null;
        InputStream is = null;
        try {
            //根据id和文件名获取真实的放在磁盘上的文件
            AttachmentInfoEntity attachmentInfoEntity = attachmentInfoService.getAttach(attachId);
            String attachPath = attachmentInfoEntity.getAttachPath();
            if (org.apache.commons.lang3.StringUtils.isNotBlank(attachPath)) {
                // 防乱码
//                    String name =
//                        new String(realFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
                ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                assert requestAttributes != null;
                HttpServletResponse response = requestAttributes.getResponse();
                assert response != null;
                response.reset();
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(attachmentInfoEntity.getAttachName(), "UTF-8") + "\"");
                // 跨域
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setHeader("Access-Control-Allow-Method", "POST,GET");
                String name = attachmentInfoEntity.getFileDirId() + attachPath;
                is = new FileInputStream(new File(name));

                // PrintWrite pw=response.getWriter();  或
                os = response.getOutputStream();
                int flag = 0;
                while ((flag = is.read()) != -1) {
                    os.write(flag);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (os != null) {
                    os.flush();
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 删除附件
     *
     * @param map
     * @return
     */
    @PostMapping("/deleteFile")
    public RestResponse deleteFile(@RequestBody Map<String, String> map) {
        RestResponse response = null;
        try {
            if (!PlatformObjectUtils.isEmpty(map.get("attachId"))) {
                boolean res = attachmentInfoService.deleteFile(map.get("attachId"));
                if (res) {
                    response = RestResponse.succeed("附件删除成功!");
                    response.setMessage("附件删除成功!");
                }

            } else {
                response = RestResponse.fail("附件删除失败! attachId为空!");
            }
        } catch (Exception e) {
            log.error("附件删除失败!", e);
            response = RestResponse.fail("附件删除失败!");
        }
        return response;
    }

    @PostMapping("/downForZip/{attachIds}")
    public void plistDownLoad(HttpServletResponse response, @PathVariable("attachIds") List<String> attachIds) throws Exception {
//     此处处理attachIds,拿到文件下载url

        List<AttachmentInfoEntity> attachmentInfoEntities = new ArrayList<>();
        for (String attachId : attachIds) {
            AttachmentInfoEntity attachmentInfoEntity = attachmentInfoService.getAttach(attachId);
            if (attachmentInfoEntity == null) {
                return;
            }
            attachmentInfoEntities.add(attachmentInfoEntity);
        }
        if (attachmentInfoEntities.size() != 0) {
            // 创建临时路径,存放压缩文件
            String zipFilePath = "D:\\我的压缩文件.zip";
            // 压缩输出流,包装流,将临时文件输出流包装成压缩流,将所有文件输出到这里,打成zip包

            ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath));
            // 循环调用压缩文件方法,将一个一个需要下载的文件打入压缩文件包
            int count = 0;
            for (AttachmentInfoEntity attachmentInfoEntity : attachmentInfoEntities) {
                String path = attachmentInfoEntity.getFileDirId() + attachmentInfoEntity.getAttachPath();
                String name = attachmentInfoEntity.getAttachName();
                count++;
                name = "(" + count + ")" + name;
                fileToZip(path, name, zipOut);


            }
            // 压缩完成后,关闭压缩流
            zipOut.close();

            //拼接下载默认名称并转为ISO-8859-1格式
            String fileName = new String(("我的压缩文件.zip").getBytes(), "ISO-8859-1");
            response.setHeader("Content-Disposition", "attchment;filename=" + fileName);
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Method", "POST,GET");
            //该流不可以手动关闭,手动关闭下载会出问题,下载完成后会自动关闭
            ServletOutputStream outputStream = response.getOutputStream();
            FileInputStream inputStream = new FileInputStream(zipFilePath);
            // copy方法为文件复制,在这里直接实现了下载效果
            IOUtils.copy(inputStream, outputStream);

            // 关闭输入流
            inputStream.close();

            //下载完成之后，删掉这个zip包
            File fileTempZip = new File(zipFilePath);
            fileTempZip.delete();
        }
    }

    public static void fileToZip(String filePath, String fileName, ZipOutputStream zipOut) throws IOException {
        // 需要压缩的文件
        File file = new File(filePath);
        FileInputStream fileInput = new FileInputStream(filePath);
        // 缓冲
        byte[] bufferArea = new byte[1024 * 10];
        BufferedInputStream bufferStream = new BufferedInputStream(fileInput, 1024 * 10);
        // 将当前文件作为一个zip实体写入压缩流,fileName代表压缩文件中的文件名称

        zipOut.putNextEntry(new ZipEntry(fileName));

        int length = 0;
        while ((length = bufferStream.read(bufferArea, 0, 1024 * 10)) != -1) {
            zipOut.write(bufferArea, 0, length);
        }
        //关闭流
        fileInput.close();
        // 需要注意的是缓冲流必须要关闭流,否则输出无效
        bufferStream.close();
        // 压缩流不必关闭,使用完后再关
    }





    public List<String> uploadFileLittleReport(List<MultipartFile> file) throws IOException {
        RestResponse restResponse = null;
        List<String> attachmentInfoIdList = new ArrayList<String>();
        List<AttachmentInfoEntity> attachmentInfoEntities = new ArrayList<>();
        List<String> idList=new ArrayList<>();
        for(int i = 0;i<file.size();i++){
            if(file.get(i) != null){
                MultipartFile multipartFile = file.get(i);
                    //获取文件名称
                    String fileName=multipartFile.getOriginalFilename();
                    //获取文件上传的本地路径
                    String dateDir = new SimpleDateFormat("/yyyy/MM/dd").format(new Date());
                    String savePath = localDir + dateDir;
                    //构建文件
                    assert fileName != null;
                    //上传文件
                    String realFileName = uploadFile(fileName,savePath,multipartFile);
                    //构建实体类
                    AttachmentInfoEntity attachmentInfoEntity = buildAttachment(fileName,dateDir,realFileName);
                    attachmentInfoIdList.add(attachmentInfoEntity.getAttachId());
                    attachmentInfoEntities.add(attachmentInfoEntity);
                    idList.add(attachmentInfoEntity.getAttachId());
            }
        }
        int flag = 0;
        //保存附件到数据库
        if(ObjectUtils.isNotEmpty(attachmentInfoEntities)){
            flag = attachmentInfoService.save(attachmentInfoEntities);
        }

        return idList;
    }



    @Resource
    private ReportTemplateRepository reportTemplateRepository;
    /*
    * 生成报告 并且报告回显接口
    *
    * */
    public RestResponse uploadFileLittleReport(List<MultipartFile> file,String iaId,String number){
        RestResponse restResponse = null;
        if (file.size()==0) {
            restResponse = RestResponse.fail("上传失败，请选择文件");
            return restResponse;
        }
        if(file.size()>50){
            restResponse = RestResponse.fail("上传失败，请将上传的文件控制在50个以内");
            return restResponse;
        }
        List<String> attachmentInfoIdList = new ArrayList<String>();
        List<AttachmentInfoEntity> attachmentInfoEntities = new ArrayList<>();
        for(int i = 0;i<file.size();i++){
            if(file.get(i) != null){
                MultipartFile multipartFile = file.get(i);
                try {
                    //获取文件名称
                    String fileName=multipartFile.getOriginalFilename();
                    //获取文件上传的本地路径
                    String dateDir = new SimpleDateFormat("/yyyy/MM/dd").format(new Date());
                    String savePath = localDir + dateDir;
                    //构建文件
                    assert fileName != null;
                    //上传文件
                    String realFileName = uploadFile(fileName,savePath,multipartFile);
                    //构建实体类
                    AttachmentInfoEntity attachmentInfoEntity = buildAttachment(fileName,dateDir,realFileName);
                    attachmentInfoIdList.add(attachmentInfoEntity.getAttachId());
                    attachmentInfoEntities.add(attachmentInfoEntity);
                    List<ReportHuiXianEntity> reportHuiXianEntities= reportTemplateRepository.getReportHuiXianByIaIdAndNumber(iaId,number);
                    if (PlatformObjectUtils.isEmpty(reportHuiXianEntities)){
                        reportTemplateRepository.insertReportHuiXian(iaId,attachmentInfoEntity.getAttachId(),attachmentInfoEntity.getAttachName(),number);
                    }else {
                        reportTemplateRepository.updateReportHuiXian(iaId,attachmentInfoEntity.getAttachId(),attachmentInfoEntity.getAttachName(),number);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    restResponse = RestResponse.fail("文件上传失败");
                    return restResponse;
                }
            }
        }
        int flag = 0;
        //保存附件到数据库
        if(ObjectUtils.isNotEmpty(attachmentInfoEntities)){
            flag = attachmentInfoService.save(attachmentInfoEntities);
        }

        //上传成功返回文件名用于业务实体保存
        if(flag==1){
            restResponse = RestResponse.succeed(attachmentInfoEntities);
            restResponse.setMessage("上传成功!");
        } else {
            restResponse = RestResponse.fail("文件上传失败");
        }
        return restResponse;
    }


    /**
     * 超图工作空间文件上传
     */
    @PostMapping("/uploadSmwuFile")
    public RestResponse uploadSmwuFile(List<MultipartFile> file){
        RestResponse restResponse = null;
        if (file.size()==0) {
            restResponse = RestResponse.fail("上传失败，请选择文件");
            return restResponse;
        }
        if(file.size()>2){
            restResponse = RestResponse.fail("上传失败，请上传2个文件，包括.smwu文件和.udbx文件");
            return restResponse;
        }
        List<String> attachmentInfoIdList = new ArrayList<String>();
        List<AttachmentInfoEntity> attachmentInfoEntities = new ArrayList<>();
        for(int i = 0;i<file.size();i++){
            if(file.get(i) != null){
                MultipartFile multipartFile = file.get(i);
                try {
                    //获取文件名称
                    String fileName=multipartFile.getOriginalFilename();
                    //获取文件上传的本地路径
                    String dateDir = new SimpleDateFormat("/yyyy/MM/dd").format(new Date());
                    String savePath = localDir + dateDir;
                    //获取新的交通网络分析服务版本号
                    String version = hypergraphService.getNetworkanalystVersionCode();
                    String folder = "/超图工作空间数据编号" + version;
                    savePath += folder;
                    //构建文件
                    assert fileName != null;
                    //上传文件
                    String realFileName = uploadSmwuFile(fileName,savePath,multipartFile);
                    //构建实体类
                    AttachmentInfoEntity attachmentInfoEntity = buildAttachmentSmwu(fileName,dateDir,folder,realFileName);
                    attachmentInfoIdList.add(attachmentInfoEntity.getAttachId());
                    attachmentInfoEntities.add(attachmentInfoEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                    restResponse = RestResponse.fail("文件上传失败");
                    return restResponse;
                }
            }
        }
        int flag = 0;
        //保存附件到数据库
        if(ObjectUtils.isNotEmpty(attachmentInfoEntities)){
            flag = attachmentInfoService.save(attachmentInfoEntities);
        }

        //上传成功返回文件名用于业务实体保存
        if(flag==1){
            restResponse = RestResponse.succeed(attachmentInfoEntities);
            restResponse.setMessage("上传成功!");
        } else {
            restResponse = RestResponse.fail("文件上传失败");
        }
        return restResponse;
    }

    /**
     * 超图工作空间文件上传
     */
    @PostMapping("/uploadSmwuFile1")
    public RestResponse uploadSmwuFile1(List<MultipartFile> file){
        RestResponse restResponse = null;
        if (file.size()==0) {
            restResponse = RestResponse.fail("上传失败，请选择文件");
            return restResponse;
        }
        if(file.size()>2){
            restResponse = RestResponse.fail("上传失败，请上传2个文件，包括.smwu文件和.udbx文件");
            return restResponse;
        }
        List<String> attachmentInfoIdList = new ArrayList<String>();
        List<AttachmentInfoEntity> attachmentInfoEntities = new ArrayList<>();
        for(int i = 0;i<file.size();i++){
            if(file.get(i) != null){
                MultipartFile multipartFile = file.get(i);
                try {
                    //获取文件名称
                    String fileName=multipartFile.getOriginalFilename();
                    //获取文件上传的本地路径
                    String dateDir = new SimpleDateFormat("/yyyy/MM/dd").format(new Date());
                    String savePath = localDir + dateDir;
                    //获取新的地图服务版本号
                    String version = hypergraphService.getNewWorkspaceVersionCode();
                    String folder = "/超图工作空间数据编号" + version;
                    savePath += folder;
                    //构建文件
                    assert fileName != null;
                    //上传文件
                    String realFileName = uploadSmwuFile(fileName,savePath,multipartFile);
                    //构建实体类
                    AttachmentInfoEntity attachmentInfoEntity = buildAttachmentSmwu(fileName,dateDir,folder,realFileName);
                    attachmentInfoIdList.add(attachmentInfoEntity.getAttachId());
                    attachmentInfoEntities.add(attachmentInfoEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                    restResponse = RestResponse.fail("文件上传失败");
                    return restResponse;
                }
            }
        }
        int flag = 0;
        //保存附件到数据库
        if(ObjectUtils.isNotEmpty(attachmentInfoEntities)){
            flag = attachmentInfoService.save(attachmentInfoEntities);
        }

        //上传成功返回文件名用于业务实体保存
        if(flag==1){
            restResponse = RestResponse.succeed(attachmentInfoEntities);
            restResponse.setMessage("上传成功!");
        } else {
            restResponse = RestResponse.fail("文件上传失败");
        }
        return restResponse;
    }

    private String uploadSmwuFile(String fileName, String savePath, MultipartFile multipartFile) throws IOException {
        // 获取文件的后缀名
        assert fileName != null;
        // 拼文件名  真实的文件名称
        String realFileName = fileName;
        //判断文件夹是否存在如果不存在则创建
        if (!new File(savePath).exists()) {
            new File(savePath).mkdirs();
        }
        File file = new File(savePath, realFileName);
        multipartFile.transferTo(file);
        return realFileName;
    }

    private AttachmentInfoEntity buildAttachmentSmwu(String fileName, String dateDir, String folder, String realFileName) {
        AttachmentInfoEntity attachmentInfoEntity = new AttachmentInfoEntity();
        attachmentInfoEntity.setAttachId(StringUtils.buildPrimaryId());
        attachmentInfoEntity.setAttachName(fileName);
        attachmentInfoEntity.setAttachPath(dateDir + folder + "/" + realFileName);
        attachmentInfoEntity.setFileDirId(localDir);
        attachmentInfoEntity.setIsValid("1");
        attachmentInfoEntity.setIsCompleted("1");
        return attachmentInfoEntity;
    }
}
